/*
 * Copyright (c) OSGi Alliance (2012, 2013). All Rights Reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.osgi.service.subsystem;

import java.io.InputStream;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.resource.Resource;

/**
 * A subsystem is a collection of resources constituting a logical, possibly
 * isolated, unit of functionality.
 * 
 * <p>
 * A subsystem may be <i>scoped</i> or <i>unscoped</i>. Scoped subsystems are
 * isolated by implicit or explicit sharing policies. Unscoped subsystems are
 * not isolated and, therefore, have no sharing policy. There are three standard
 * {@link SubsystemConstants#SUBSYSTEM_TYPE types} of subsystems.
 * <ul>
 * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_APPLICATION Application} - An
 * implicitly scoped subsystem. Nothing is exported, and imports are computed
 * based on any unsatisfied content requirements.</li>
 * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_COMPOSITE Composite} - An
 * explicitly scoped subsystem. The sharing policy is defined by metadata within
 * the subsystem archive.</li>
 * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_FEATURE Feature} - An unscoped
 * subsystem.</li>
 * </ul>
 * Conceptually, a subsystem may be thought of as existing in an isolated region
 * along with zero or more other subsystems. Each region has one and only one
 * scoped subsystem, which dictates the sharing policy. The region may, however,
 * have many unscoped subsystems. It is, therefore, possible to have shared
 * constituents across multiple subsystems within a region. Associated with each
 * region is a bundle whose context may be {@link #getBundleContext() retrieved}
 * from any subsystem within that region. This context may be used to monitor
 * activity occurring within the region.
 * 
 * <p>
 * A subsystem may have {@link #getChildren() children} and, unless it's the
 * root subsystem, must have at least one {@link #getParents() parent}.
 * Subsystems become children of the subsystem in which they are installed.
 * Unscoped subsystems have more than one parent if they are installed in more
 * than one subsystem within the same region. The subsystem graph may be thought
 * of as an <a
 * href="https://en.wikipedia.org/wiki/Directed_acyclic_graph">acyclic
 * digraph</a> with one and only one source vertex, which is the root subsystem.
 * The edges have the child as the head and parent as the tail.
 * 
 * <p>
 * A subsystem has several identifiers.
 * <ul>
 * <li>{@link #getLocation() Location} - An identifier specified by the client
 * as part of installation. It is guaranteed to be unique within the same
 * framework.</li>
 * <li>{@link #getSubsystemId() ID} - An identifier generated by the
 * implementation as part of installation. It is guaranteed to be unique within
 * the same framework.</li>
 * <li>{@link #getSymbolicName() Symbolic Name}/{@link #getVersion() Version} -
 * The combination of symbolic name and version is guaranteed to be unique
 * within the same region. Although {@link #getType() type} is not formally part
 * of the identity, two subsystems with the same symbolic names and versions but
 * different types are not considered to be equal.</li>
 * </ul>
 * A subsystem has a well-defined {@link State life cycle}. Which stage a
 * subsystem is in may be obtained from the subsystem's {@link #getState()
 * state} and is dependent on which life cycle operation is currently active or
 * was last invoked.
 * 
 * <p>
 * A subsystem archive is a ZIP file having an {@code .esa} extension and
 * containing metadata describing the subsystem. The form of the metadata may be
 * a subsystem or deployment manifest, as well as any content resource files.
 * The manifests are optional and will be computed if not present. The subsystem
 * manifest headers may be {@link #getSubsystemHeaders(Locale) retrieved} in raw
 * or localized forms. There are five standard
 * {@link IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE types} of resources that
 * may be included in a subsystem.
 * <ul>
 * <li>{@link IdentityNamespace#TYPE_BUNDLE Bundle} - A bundle that is not a
 * fragment.</li>
 * <li>{@link IdentityNamespace#TYPE_FRAGMENT Fragment} - A fragment bundle.</li>
 * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_APPLICATION Application
 * Subsystem} - An application subsystem.</li>
 * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_COMPOSITE Composite Subsystem} -
 * A composite subsystem.</li>
 * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_FEATURE Feature Subsystem} - A
 * feature subsystem.</li>
 * </ul>
 * Resources contained by a subsystem are called {@link #getConstituents()
 * constituents}. There are several ways a resource may become a constituent of
 * a subsystem:
 * <ul>
 * <li>A resource is listed as part of the subsystem's content.</li>
 * <li>A subsystem resource is a child of the subsystem.</li>
 * <li>The subsystem has a provision policy of accept dependencies.</li>
 * <li>A bundle resource is installed using the region bundle context.</li>
 * <li>A bundle resource is installed using the bundle context of another
 * resource contained by the subsystem.</li>
 * </ul>
 * 
 * <p>
 * In addition to invoking one of the install methods, a subsystem instance may
 * be obtained through the service registry. Each installed subsystem has a
 * corresponding service registration. A subsystem service has the following
 * properties.
 * 
 * <ul>
 * <li>{@link SubsystemConstants#SUBSYSTEM_ID_PROPERTY ID} - The ID of the
 * subsystem.</li>
 * <li>{@link SubsystemConstants#SUBSYSTEM_SYMBOLICNAME_PROPERTY Symbolic Name}
 * - The symbolic name of the subsystem.</li>
 * <li>{@link SubsystemConstants#SUBSYSTEM_VERSION_PROPERTY Version} - The
 * version of the subsystem.</li>
 * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_PROPERTY Type} - The type of the
 * subsystem.</li>
 * <li>{@link SubsystemConstants#SUBSYSTEM_STATE_PROPERTY State} - The state of
 * the subsystem.</li>
 * </ul>
 * 
 * <p>
 * Because a subsystem must be used to install other subsystems, a root
 * subsystem is provided as a starting point. The root subsystem may only be
 * obtained as a service and has the following characteristics.
 * 
 * <ul>
 * <li>The ID is {@code 0}.</li>
 * <li>The symbolic name is
 * {@link SubsystemConstants#ROOT_SUBSYSTEM_SYMBOLICNAME
 * org.osgi.service.subsystem.root}.</li>
 * <li>The version matches this specification's version.</li>
 * <li>It has no parents.</li>
 * <li>All existing bundles, including the system and subsystem implementation
 * bundles, are constituents.</li>
 * <li>The type is {@link SubsystemConstants#SUBSYSTEM_TYPE_APPLICATION
 * osgi.subsystem.application} with no imports.</li>
 * <li>The provision policy is
 * {@link SubsystemConstants#PROVISION_POLICY_ACCEPT_DEPENDENCIES
 * acceptDependencies}.</li>
 * </ul>
 * 
 * @ThreadSafe
 * @noimplement
 * @author $Id: 98c29e1bfd80828ab025a1aa0530019184185242 $
 */
public interface Subsystem {
	/**
	 * An enumeration of the possible states of a subsystem.
	 * 
	 * <p>
	 * These states are a reflection of what constituent resources are permitted
	 * to do and not an aggregation of constituent resource states.
	 */
	public static enum State {
		/**
		 * The subsystem is in the process of installing.
		 * <p>
		 * A subsystem is in the {@code INSTALLING} state when the
		 * {@link Subsystem#install(String, InputStream) install} method of its
		 * parent is active, and attempts are being made to install its content
		 * resources. If the install method completes without exception, then
		 * the subsystem has successfully installed and must move to the
		 * {@link #INSTALLED} state. Otherwise, the subsystem has failed to
		 * install and must move to the {@link #INSTALL_FAILED} state.
		 */
		INSTALLING,
		/**
		 * The subsystem is installed but not yet resolved.
		 * <p>
		 * A subsystem is in the {@code INSTALLED} state when it has been
		 * installed in a parent subsystem but is not or cannot be resolved.
		 * This state is visible if the dependencies of the subsystem's content
		 * resources cannot be resolved.
		 */
		INSTALLED,
		/**
		 * The subsystem failed to install.
		 * <p>
		 * A subsystem is in the {@code INSTALL_FAILED} state when an
		 * unrecoverable error occurred during installation. The subsystem is in
		 * an unusable state but references to the subsystem object may still be
		 * available and used for introspection.
		 */
		INSTALL_FAILED,
		/**
		 * The subsystem is in the process of resolving.
		 * <p>
		 * A subsystem is in the {@code RESOLVING} state when the
		 * {@link Subsystem#start() start} method is active, and attempts are
		 * being made to resolve its content resources. If the resolve method
		 * completes without exception, then the subsystem has successfully
		 * resolved and must move to the {@link #RESOLVED} state. Otherwise, the
		 * subsystem has failed to resolve and must move to the INSTALLED state.
		 */
		RESOLVING,
		/**
		 * The subsystem is resolved and able to be started.
		 * <p>
		 * A subsystem is in the {@code RESOLVED} state when all of its content
		 * resources are resolved. Note that the subsystem is not active yet.
		 */
		RESOLVED,
		/**
		 * The subsystem is in the process of starting.
		 * <p>
		 * A subsystem is in the {@code STARTING} state when its
		 * {@link Subsystem#start() start} method is active, and attempts are
		 * being made to start its content and dependencies. If the start method
		 * completes without exception, then the subsystem has successfully
		 * started and must move to the {@link #ACTIVE} state. Otherwise, the
		 * subsystem has failed to start and must move to the {@link #RESOLVED}
		 * state.
		 */
		STARTING,
		/**
		 * The subsystem is now running.
		 * <p>
		 * A subsystem is in the {@code ACTIVE} state when its content and
		 * dependencies have been successfully started.
		 */
		ACTIVE,
		/**
		 * The subsystem is in the process of stopping.
		 * <p>
		 * A subsystem is in the {@code STOPPING} state when its
		 * {@link Subsystem#stop() stop} method is active, and attempts are
		 * being made to stop its content and dependencies. When the stop method
		 * completes, the subsystem is stopped and must move to the
		 * {@link #RESOLVED} state.
		 */
		STOPPING,
		/**
		 * The subsystem is in the process of uninstalling.
		 * <p>
		 * A subsystem is in the {@code UNINSTALLING} state when its
		 * {@link Subsystem#uninstall() uninstall} method is active, and
		 * attempts are being made to uninstall its constituent and
		 * dependencies. When the uninstall method completes, the subsystem is
		 * uninstalled and must move to the {@link #UNINSTALLED} state.
		 */
		UNINSTALLING,
		/**
		 * The subsystem is uninstalled and may not be used.
		 * <p>
		 * The {@code UNINSTALLED} state is only visible after a subsystem's
		 * constituent and dependencies are uninstalled. The subsystem is in an
		 * unusable state but references to the subsystem object may still be
		 * available and used for introspection.
		 */
		UNINSTALLED
	}

	/**
	 * Returns the bundle context of the region within which this subsystem
	 * resides.
	 * <p>
	 * The bundle context offers the same perspective of any resource contained
	 * by a subsystem within the region. It may be used, for example, to monitor
	 * events internal to the region as well as external events visible to the
	 * region. All subsystems within the same region have the same bundle
	 * context. If this subsystem is in a state where the bundle context would
	 * be invalid, {@code null} is returned.
	 * 
	 * @return The bundle context of the region within which this subsystem
	 *         resides or {@code null} if this subsystem's state is in
	 *         {@link State#INSTALL_FAILED INSTALL_FAILED},
	 *         {@link State#UNINSTALLED UNINSTALLED}.
	 * @throws SecurityException If the caller does not have the appropriate
	 *         {@link SubsystemPermission}[this,CONTEXT], and the runtime
	 *         supports permissions.
	 */
	public BundleContext getBundleContext();

	/**
	 * Returns the child subsystems of this subsystem.
	 * 
	 * @return The child subsystems of this subsystem. The returned collection
	 *         is an unmodifiable snapshot of all subsystems that are installed
	 *         in this subsystem. The collection will be empty if no subsystems
	 *         are installed in this subsystem.
	 * @throws IllegalStateException If this subsystem's state is in
	 *         {@link State#INSTALL_FAILED INSTALL_FAILED},
	 *         {@link State#UNINSTALLED UNINSTALLED}.
	 */
	public Collection<Subsystem> getChildren();

	/**
	 * Returns the headers for this subsystem's subsystem manifest.
	 * <p>
	 * Each key in the map is a header name and the value of the key is the
	 * corresponding header value. Because header names are case-insensitive,
	 * the methods of the map must treat the keys in a case-insensitive manner.
	 * If the header name is not found, {@code null} is returned. Both original
	 * and derived headers will be included in the map.
	 * <p>
	 * This method must continue to return the headers while this subsystem is
	 * in the {@link State#INSTALL_FAILED INSTALL_FAILED} or
	 * {@link State#UNINSTALLED UNINSTALLED} states.
	 * 
	 * @param locale The locale for which translations are desired. The header
	 *        values are translated according to the specified locale. If the
	 *        specified locale is {@code null} or not supported, the raw values
	 *        are returned. If the translation for a particular header is not
	 *        found, the raw value is returned.
	 * @return The headers for this subsystem's subsystem manifest. The returned
	 *         map is unmodifiable.
	 * @throws SecurityException If the caller does not have the appropriate
	 *         {@link SubsystemPermission}[this,METADATA], and the runtime
	 *         supports permissions.
	 */
	public Map<String, String> getSubsystemHeaders(Locale locale);

	/**
	 * Returns the location identifier of this subsystem.
	 * <p>
	 * The location identifier is the {@code location} that was passed to the
	 * {@link #install(String, InputStream) install} method of the
	 * {@link #getParents() parent} subsystem. It is unique within the
	 * framework.
	 * <p>
	 * This method must continue to return this subsystem's headers while this
	 * subsystem is in the {@link State#INSTALL_FAILED INSTALL_FAILED} or
	 * {@link State#UNINSTALLED UNINSTALLED} states.
	 * 
	 * @return The location identifier of this subsystem.
	 * @throws SecurityException If the caller does not have the appropriate
	 *         {@link SubsystemPermission}[this,METADATA], and the runtime
	 *         supports permissions.
	 */
	public String getLocation();

	/**
	 * Returns the parent subsystems of this subsystem.
	 * 
	 * @return The parent subsystems of this subsystem. The returned collection
	 *         is an unmodifiable snapshot of all subsystems in which this
	 *         subsystem is installed. The collection will be empty for the root
	 *         subsystem; otherwise, it must contain at least one parent. Scoped
	 *         subsystems always have only one parent. Unscoped subsystems may
	 *         have multiple parents.
	 * @throws IllegalStateException If this subsystem's state is in
	 *         {@link State#INSTALL_FAILED INSTALL_FAILED},
	 *         {@link State#UNINSTALLED UNINSTALLED}.
	 */
	public Collection<Subsystem> getParents();

	/**
	 * Returns the constituent resources of this subsystem.
	 * 
	 * @return The constituent resources of this subsystem. The returned
	 *         collection is an unmodifiable snapshot of the constituent
	 *         resources of this subsystem. If this subsystem has no
	 *         constituents, the collection will be empty.
	 * @throws IllegalStateException If this subsystem's state is in
	 *         {@link State#INSTALL_FAILED INSTALL_FAILED},
	 *         {@link State#UNINSTALLED UNINSTALLED}.
	 */
	public Collection<Resource> getConstituents();

	/**
	 * Returns the current state of this subsystem.
	 * <p>
	 * This method must continue to return this subsystem's state while this
	 * subsystem is in the {@link State#INSTALL_FAILED INSTALL_FAILED} or
	 * {@link State#UNINSTALLED UNINSTALLED} states.
	 * 
	 * @return The current state of this subsystem.
	 */
	public State getState();

	/**
	 * Returns the identifier of this subsystem.
	 * <p>
	 * The identifier is a monotonically increasing, non-negative integer
	 * automatically generated at installation time and guaranteed to be unique
	 * within the framework. The identifier of the root subsystem is zero.
	 * <p>
	 * This method must continue to return this subsystem's identifier while
	 * this subsystem is in the {@link State#INSTALL_FAILED INSTALL_FAILED} or
	 * {@link State#UNINSTALLED UNINSTALLED} states.
	 * 
	 * @return The identifier of this subsystem.
	 */
	public long getSubsystemId();

	/**
	 * Returns the symbolic name of this subsystem.
	 * <p>
	 * The subsystem symbolic name conforms to the same grammar rules as the
	 * bundle symbolic name and is derived from one of the following, in order.
	 * <ul>
	 * <li>The value of the {@link SubsystemConstants#SUBSYSTEM_SYMBOLICNAME
	 * Subsystem-SymbolicName} header, if specified.</li>
	 * <li>The subsystem URI if passed as the {@code location} along with the
	 * {@code content} to the {@link #install(String, InputStream) install}
	 * method.</li>
	 * <li>Optionally generated in an implementation specific way.</li>
	 * </ul>
	 * The combination of subsystem symbolic name and {@link #getVersion()
	 * version} is unique within a region. The symbolic name of the root
	 * subsystem is {@link SubsystemConstants#ROOT_SUBSYSTEM_SYMBOLICNAME
	 * org.osgi.service.subsystem.root}.
	 * <p>
	 * This method must continue to return this subsystem's symbolic name while
	 * this subsystem is in the {@link State#INSTALL_FAILED INSTALL_FAILED} or
	 * {@link State#UNINSTALLED UNINSTALLED} states.
	 * 
	 * @return The symbolic name of this subsystem.
	 */
	public String getSymbolicName();

	/**
	 * Returns the {@link SubsystemConstants#SUBSYSTEM_TYPE type} of this
	 * subsystem.
	 * <p>
	 * This method must continue to return this subsystem's type while this
	 * subsystem is in the {@link State#INSTALL_FAILED INSTALL_FAILED} or
	 * {@link State#UNINSTALLED UNINSTALLED} states.
	 * 
	 * @return The type of this subsystem.
	 */
	public String getType();

	/**
	 * Returns the {@link SubsystemConstants#SUBSYSTEM_VERSION version} of this
	 * subsystem.
	 * <p>
	 * The subsystem version conforms to the same grammar rules as the bundle
	 * version and is derived from one of the following, in order.
	 * <ul>
	 * <li>The value of the {@link SubsystemConstants#SUBSYSTEM_VERSION
	 * Subsystem-Version} header, if specified.</li>
	 * <li>The subsystem URI if passed as the {@code location} along with the
	 * {@code content} to the {@link #install(String, InputStream) install}
	 * method.</li>
	 * <li>Defaults to {@code 0.0.0}.</li>
	 * </ul>
	 * The combination of subsystem {@link #getSymbolicName() symbolic name} and
	 * version is unique within a region. The version of the root subsystem
	 * matches this specification's version.
	 * <p>
	 * This method must continue to return this subsystem's version while this
	 * subsystem is in the {@link State#INSTALL_FAILED INSTALL_FAILED} or
	 * {@link State#UNINSTALLED UNINSTALLED} states.
	 * 
	 * @return The version of this subsystem.
	 */
	public Version getVersion();

	/**
	 * Installs a subsystem from the specified location identifier.
	 * <p>
	 * This method performs the same function as calling
	 * {@link #install(String, InputStream)} with the specified location
	 * identifier and {@code null} as the content.
	 * 
	 * @param location The location identifier of the subsystem to install.
	 * @return The installed subsystem.
	 * @throws IllegalStateException If this subsystem's state is in
	 *         {@link State#INSTALLING INSTALLING}, {@link State#INSTALL_FAILED
	 *         INSTALL_FAILED}, {@link State#UNINSTALLING UNINSTALLING},
	 *         {@link State#UNINSTALLED UNINSTALLED}.
	 * @throws SubsystemException If the installation failed.
	 * @throws SecurityException If the caller does not have the appropriate
	 *         {@link SubsystemPermission}[installed subsystem,LIFECYCLE], and
	 *         the runtime supports permissions.
	 * @see #install(String, InputStream)
	 */
	public Subsystem install(String location);

	/**
	 * Installs a subsystem from the specified content.
	 * <p>
	 * The specified location will be used as an identifier of the subsystem.
	 * Every installed subsystem is uniquely identified by its location, which
	 * is typically in the form of a URI. If the specified location conforms to
	 * the {@code subsystem-uri} grammar, the required symbolic name and
	 * optional version information will be used as default values.
	 * <p>
	 * If the specified content is {@code null}, a new input stream must be
	 * created from which to read the subsystem by interpreting, in an
	 * implementation dependent manner, the specified location.
	 * <p>
	 * A subsystem installation must be persistent. That is, an installed
	 * subsystem must remain installed across Framework and VM restarts.
	 * <p>
	 * All references to changing the state of this subsystem include both
	 * changing the state of the subsystem object as well as the state property
	 * of the subsystem service registration.
	 * <p>
	 * The following steps are required to install a subsystem.
	 * <ol>
	 * <li>If an installed subsystem with the specified location identifier
	 * already exists, return the installed subsystem.</li>
	 * <li>Read the specified content in order to determine the symbolic name,
	 * version, and type of the installing subsystem. If an error occurs while
	 * reading the content, an installation failure results.</li>
	 * <li>If an installed subsystem with the same symbolic name and version
	 * already exists within this subsystem's region, complete the installation
	 * with one of the following.
	 * <ul>
	 * <li>If the installing and installed subsystems' types are not equal, an
	 * installation failure results.</li>
	 * <li>If the installing and installed subsystems' types are equal, and the
	 * installed subsystem is already a child of this subsystem, return the
	 * installed subsystem.</li>
	 * <li>If the installing and installed subsystems' types are equal, and the
	 * installed subsystem is not already a child of this subsystem, add the
	 * installed subsystem as a child of this subsystem, increment the installed
	 * subsystem's reference count by one, and return the installed subsystem.</li>
	 * </ul>
	 * <li>Create a new subsystem based on the specified location and content.</li>
	 * <li>If the subsystem is scoped, install and start a new region context
	 * bundle.</li>
	 * <li>Change the state to {@link State#INSTALLING INSTALLING} and register
	 * a new subsystem service.</li>
	 * <li>Discover the subsystem's content resources. If any mandatory resource
	 * is missing, an installation failure results.</li>
	 * <li>Discover the dependencies required by the content resources. If any
	 * mandatory dependency is missing, an installation failure results.</li>
	 * <li>Using a framework {@code ResolverHook}, disable runtime resolution
	 * for the resources.</li>
	 * <li>For each resource, increment the reference count by one. If the
	 * reference count is one, install the resource. If an error occurs while
	 * installing a resource, an install failure results with that error as the
	 * cause.</li>
	 * <li>If the subsystem is scoped, enable the import sharing policy.</li>
	 * <li>Enable runtime resolution for the resources.</li>
	 * <li>Change the state of the subsystem to {@link State#INSTALLED
	 * INSTALLED}.</li>
	 * <li>Return the new subsystem.</li>
	 * </ol>
	 * <p>
	 * Implementations should be sensitive to the potential for long running
	 * operations and periodically check the current thread for interruption. An
	 * interrupted thread should result in a {@link SubsystemException} with an
	 * InterruptedException as the cause and be treated as an installation
	 * failure.
	 * <p>
	 * All installation failure flows include the following, in order.
	 * <ol>
	 * <li>Change the state to {@link State#INSTALL_FAILED INSTALL_FAILED}.</li>
	 * <li>Change the state to {@link State#UNINSTALLING UNINSTALLING}.</li>
	 * <li>All content and dependencies which may have been installed by the
	 * installing process must be uninstalled.</li>
	 * <li>Change the state to {@link State#UNINSTALLED UNINSTALLED}.</li>
	 * <li>Unregister the subsystem service.</li>
	 * <li>If the subsystem is a scoped subsystem then, uninstall the region
	 * context bundle.</li>
	 * <li>Throw a {@link SubsystemException} with the cause of the installation
	 * failure.</li>
	 * </ol>
	 * 
	 * @param location The location identifier of the subsystem to be installed.
	 * @param content The input stream from which this subsystem will be read or
	 *        {@code null} to indicate the input stream must be created from the
	 *        specified location identifier. The input stream will always be
	 *        closed when this method completes, even if an exception is thrown.
	 * @return The installed subsystem.
	 * @throws IllegalStateException If this subsystem's state is in
	 *         {@link State#INSTALLING INSTALLING}, {@link State#INSTALL_FAILED
	 *         INSTALL_FAILED}, {@link State#UNINSTALLING UNINSTALLING},
	 *         {@link State#UNINSTALLED UNINSTALLED}.
	 * @throws SubsystemException If the installation failed.
	 * @throws SecurityException If the caller does not have the appropriate
	 *         {@link SubsystemPermission}[installed subsystem,LIFECYCLE], and
	 *         the runtime supports permissions.
	 */
	public Subsystem install(String location, InputStream content);

	/**
	 * Starts this subsystem.
	 * <p>
	 * The following table shows which actions are associated with each state.
	 * An action of {@code Wait} means this method will block until a state
	 * transition occurs, upon which the new state will be evaluated in order to
	 * determine how to proceed. If a state transition does not occur in a
	 * reasonable time while waiting then no action is taken and a
	 * SubsystemException is thrown to indicate the subsystem was unable to be
	 * started. An action of {@code Return} means this method returns
	 * immediately without taking any other action.
	 * </p>
	 * <table>
	 * <tr>
	 * <th>State</th>
	 * <th width="4">Action</th>
	 * </tr>
	 * <tr>
	 * <td>{@link State#INSTALLING INSTALLING}</td>
	 * <td>{@code Wait}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#INSTALLED INSTALLED}</td>
	 * <td>{@code Resolve}, {@code Start}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#INSTALL_FAILED INSTALL_FAILED}</td>
	 * <td>{@code IllegalStateException}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#RESOLVING RESOLVING}</td>
	 * <td>{@code Wait}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#RESOLVED RESOLVED}</td>
	 * <td>{@code Start}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#STARTING STARTING}</td>
	 * <td>{@code Wait}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#ACTIVE ACTIVE}</td>
	 * <td>{@code Return}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#STOPPING STOPPING}</td>
	 * <td>{@code Wait}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#UNINSTALLING UNINSTALLING}</td>
	 * <td>{@code IllegalStateException}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#UNINSTALLED UNINSTALLED}</td>
	 * <td>{@code IllegalStateException}</td>
	 * </tr>
	 * </table>
	 * <p>
	 * All references to changing the state of this subsystem include both
	 * changing the state of the subsystem object as well as the state property
	 * of the subsystem service registration.
	 * <p>
	 * A subsystem must be persistently started. That is, a started subsystem
	 * must be restarted across Framework and VM restarts, even if a start
	 * failure occurs.
	 * <p>
	 * The following steps are required to start this subsystem.
	 * <ol>
	 * <li>Set the subsystem <i>autostart setting</i> to <i>started</i>.</li>
	 * <li>If this subsystem is in the {@link State#RESOLVED RESOLVED} state,
	 * proceed to step 7.</li>
	 * <li>Change the state to {@link State#RESOLVING RESOLVING}.</li>
	 * <li>Resolve the content resources. A resolution failure results in a
	 * start failure with a state of {@link State#INSTALLED INSTALLED}.</li>
	 * <li>Change the state to {@link State#RESOLVED RESOLVED}.</li>
	 * <li>If this subsystem is scoped, enable the export sharing policy.</li>
	 * <li>Change the state to {@link State#STARTING STARTING}.</li>
	 * <li>For each eligible resource, increment the active use count by one. If
	 * the active use count is one, start the resource. All dependencies must be
	 * started before any content resource, and content resources must be
	 * started according to the specified
	 * {@link SubsystemConstants#START_ORDER_DIRECTIVE start order}. If an error
	 * occurs while starting a resource, a start failure results with that error
	 * as the cause.</li>
	 * <li>Change the state to {@link State#ACTIVE ACTIVE}.</li>
	 * </ol>
	 * <p>
	 * Implementations should be sensitive to the potential for long running
	 * operations and periodically check the current thread for interruption. An
	 * interrupted thread should be treated as a start failure with an
	 * {@code InterruptedException} as the cause.
	 * <p>
	 * All start failure flows include the following, in order.
	 * <ol>
	 * <li>If the subsystem state is {@link State#STARTING STARTING} then change
	 * the state to {@link State#STOPPING STOPPING} and stop all resources that
	 * were started as part of this operation.</li>
	 * <li>Change the state to either {@link State#INSTALLED INSTALLED} or
	 * {@link State#RESOLVED RESOLVED}.</li>
	 * <li>Throw a SubsystemException with the specified cause.</li>
	 * </ol>
	 * 
	 * @throws SubsystemException If this subsystem fails to start.
	 * @throws IllegalStateException If this subsystem's state is in
	 *         {@link State#INSTALL_FAILED INSTALL_FAILED},
	 *         {@link State#UNINSTALLING UNINSTALLING}, or
	 *         {@link State#UNINSTALLED UNINSTALLED}, or if the state of at
	 *         least one of this subsystem's parents is not in
	 *         {@link State#STARTING STARTING}, {@link State#ACTIVE ACTIVE}.
	 * @throws SecurityException If the caller does not have the appropriate
	 *         {@link SubsystemPermission}[this,EXECUTE], and the runtime
	 *         supports permissions.
	 */
	public void start();

	/**
	 * Stops this subsystem.
	 * <p>
	 * The following table shows which actions are associated with each state.
	 * An action of {@code Wait} means this method will block until a state
	 * transition occurs, upon which the new state will be evaluated in order to
	 * determine how to proceed. If a state transition does not occur in a
	 * reasonable time while waiting then no action is taken and a
	 * SubsystemException is thrown to indicate the subsystem was unable to be
	 * stopped. An action of {@code Return} means this method returns
	 * immediately without taking any other action.
	 * </p>
	 * <table>
	 * <tr>
	 * <th>State</th>
	 * <th width="4">Action</th>
	 * </tr>
	 * <tr>
	 * <td>{@link State#INSTALLING INSTALLING}</td>
	 * <td>{@code Wait}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#INSTALLED INSTALLED}</td>
	 * <td>{@code Return}</td>
	 * <td>
	 * <tr>
	 * <td>{@link State#INSTALL_FAILED INSTALL_FAILED}</td>
	 * <td>{@code IllegalStateException}</td>
	 * <td>
	 * <tr>
	 * <td>{@link State#RESOLVING RESOLVING}</td>
	 * <td>{@code Wait}</td>
	 * <td>
	 * <tr>
	 * <td>{@link State#RESOLVED RESOLVED}</td>
	 * <td>{@code Return}</td>
	 * <td>
	 * <tr>
	 * <td>{@link State#STARTING STARTING}</td>
	 * <td>{@code Wait}</td>
	 * <td>
	 * <tr>
	 * <td>{@link State#ACTIVE ACTIVE}</td>
	 * <td>{@code Stop}</td>
	 * <td>
	 * <tr>
	 * <td>{@link State#STOPPING STOPPING}</td>
	 * <td>{@code Wait}</td>
	 * <td>
	 * <tr>
	 * <td>{@link State#UNINSTALLING UNINSTALLING}</td>
	 * <td>{@code IllegalStateException}</td>
	 * <td>
	 * <tr>
	 * <td>{@link State#UNINSTALLED UNINSTALLED}</td>
	 * <td>{@code IllegalStateException}</td>
	 * <td>
	 * </table>
	 * <p>
	 * A subsystem must be persistently stopped. That is, a stopped subsystem
	 * must remain stopped across Framework and VM restarts.
	 * <p>
	 * All references to changing the state of this subsystem include both
	 * changing the state of the subsystem object as well as the state property
	 * of the subsystem service registration.
	 * <p>
	 * The following steps are required to stop this subsystem.
	 * <ol>
	 * <li>Set the subsystem <i>autostart setting</i> to <i>stopped</i>.</li>
	 * <li>Change the state to {@link State#STOPPING STOPPING}.</li>
	 * <li>For each eligible resource, decrement the active use count by one. If
	 * the active use count is zero, stop the resource. All content resources
	 * must be stopped before any dependencies, and content resources must be
	 * stopped in reverse {@link SubsystemConstants#START_ORDER_DIRECTIVE start
	 * order}.</li>
	 * <li>Change the state to {@link State#RESOLVED RESOLVED}.</li>
	 * </ol>
	 * With regard to error handling, once this subsystem has transitioned to
	 * the {@link State#STOPPING STOPPING} state, every part of each step above
	 * must be attempted. Errors subsequent to the first should be logged. Once
	 * the stop process has completed, a SubsystemException must be thrown with
	 * the initial error as the specified cause.
	 * <p>
	 * Implementations should be sensitive to the potential for long running
	 * operations and periodically check the current thread for interruption, in
	 * which case a SubsystemException with an InterruptedException as the cause
	 * should be thrown. If an interruption occurs while waiting, this method
	 * should terminate immediately. Once the transition to the
	 * {@link State#STOPPING STOPPING} state has occurred, however, this method
	 * must not terminate due to an interruption until the stop process has
	 * completed.
	 * 
	 * @throws SubsystemException If this subsystem fails to stop cleanly.
	 * @throws IllegalStateException If this subsystem's state is in
	 *         {@link State#INSTALL_FAILED INSTALL_FAILED},
	 *         {@link State#UNINSTALLING UNINSTALLING}, or
	 *         {@link State#UNINSTALLED UNINSTALLED}.
	 * @throws SecurityException If the caller does not have the appropriate
	 *         {@link SubsystemPermission}[this,EXECUTE], and the runtime
	 *         supports permissions.
	 */
	public void stop();

	/**
	 * Uninstalls this subsystem.
	 * <p>
	 * The following table shows which actions are associated with each state.
	 * An action of {@code Wait} means this method will block until a state
	 * transition occurs, upon which the new state will be evaluated in order to
	 * determine how to proceed. If a state transition does not occur in a
	 * reasonable time while waiting then no action is taken and a
	 * SubsystemException is thrown to indicate the subsystem was unable to be
	 * uninstalled. An action of {@code Return} means this method returns
	 * immediately without taking any other action.
	 * <table>
	 * <tr>
	 * <th>State</th>
	 * <th width="4">Action</th>
	 * </tr>
	 * <tr>
	 * <td>{@link State#INSTALLING INSTALLING}</td>
	 * <td>{@code Wait}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#INSTALLED INSTALLED}</td>
	 * <td>{@code Uninstall}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#INSTALL_FAILED INSTALL_FAILED}</td>
	 * <td>{@code Wait}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#RESOLVING RESOLVING}</td>
	 * <td>{@code Wait}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#RESOLVED RESOLVED}</td>
	 * <td>{@code Uninstall}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#STARTING STARTING}</td>
	 * <td>{@code Wait}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#ACTIVE ACTIVE}</td>
	 * <td>{@code Stop}, {@code Uninstall}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#STOPPING STOPPING}</td>
	 * <td>{@code Wait}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#UNINSTALLING UNINSTALLING}</td>
	 * <td>{@code Wait}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link State#UNINSTALLED UNINSTALLED}</td>
	 * <td>{@code Return}</td>
	 * </tr>
	 * </table>
	 * <p>
	 * All references to changing the state of this subsystem include both
	 * changing the state of the subsystem object as well as the state property
	 * of the subsystem service registration.
	 * <p>
	 * The following steps are required to uninstall this subsystem after being
	 * stopped if necessary.
	 * <ol>
	 * <li>Change the state to {@link State#INSTALLED INSTALLED}.</li>
	 * <li>Change the state to {@link State#UNINSTALLING UNINSTALLING}.</li>
	 * <li>For each referenced resource, decrement the reference count by one.
	 * If the reference count is zero, uninstall the resource. All content
	 * resources must be uninstalled before any dependencies.</li>
	 * <li>Change the state to {@link State#UNINSTALLED UNINSTALLED}.</li>
	 * <li>Unregister the subsystem service.</li>
	 * <li>If the subsystem is scoped, uninstall the region context bundle.</li>
	 * </ol>
	 * With regard to error handling, once this subsystem has transitioned to
	 * the {@link State#UNINSTALLING UNINSTALLING} state, every part of each
	 * step above must be attempted. Errors subsequent to the first should be
	 * logged. Once the uninstall process has completed, a
	 * {@code SubsystemException} must be thrown with the specified cause.
	 * <p>
	 * Implementations should be sensitive to the potential for long running
	 * operations and periodically check the current thread for interruption, in
	 * which case a {@code SubsystemException} with an
	 * {@code InterruptedException} as the cause should be thrown. If an
	 * interruption occurs while waiting, this method should terminate
	 * immediately. Once the transition to the {@link State#UNINSTALLING
	 * UNINSTALLING} state has occurred, however, this method must not terminate
	 * due to an interruption until the uninstall process has completed.
	 * 
	 * @throws SubsystemException If this subsystem fails to uninstall cleanly.
	 * @throws SecurityException If the caller does not have the appropriate
	 *         {@link SubsystemPermission}[this,LIFECYCLE], and the runtime
	 *         supports permissions.
	 */
	public void uninstall();
}
